package com.darren.center.design.patterns.command;

import com.darren.center.design.patterns.dto.Context;
import com.darren.center.design.patterns.exceptions.BizException;
import com.darren.center.design.patterns.exceptions.ApiBizException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <h3>design-patterns</h3>
 * <p></p>
 *
 * @author : Darren
 * @date : 2021年06月14日 18:38:04
 **/
public class Dispatcher {

    private static final Logger logger = LoggerFactory.getLogger(Dispatcher.class);
    private static final String FORMAT_LOG = "sequence:{}, 返回xml：{}";

    public String doAction(String reqXml, Context context) {
        String serviceCode = getServiceCode(reqXml);
        if (StringUtils.isBlank(serviceCode)) {
            return null;
        }
        String partnerId = getPartnerId(reqXml);
        try {
            logger.info("sequence:{}, 输入xml：{}", context.getMsgSeq(), reqXml);
            //reqXml = reqXml.replace("request", "Request");
            reqXml = reqXml.replace("<request>", "<Request>");
            reqXml = reqXml.replace("</request>", "</Request>");
            handlerChain.handler(reqXml, context);
            Action action = mapper.findAction(serviceCode);
            String respXml = action.doAction(reqXml, context);
            logger.info(FORMAT_LOG, context.getMsgSeq(), respXml);
            return respXml;
        } catch (BizException e) {
            String resp = null;
            if(serviceCode.indexOf("Revoke") > -1){
                resp = String.format(REVOKE_ERROR_XML, e.getCode(), e.getMsg());
                logger.error(FORMAT_LOG, context.getMsgSeq(), resp);
                return resp;
            }
            if(serviceCode.indexOf("ScanPay") > -1 || serviceCode.indexOf("F2FPay") > -1){
                resp = String.format(PAY_ERROR_XML, e.getCode(), e.getMsg());
                logger.error(FORMAT_LOG, context.getMsgSeq(), resp);
                return resp;
            }
            if(serviceCode.indexOf("Refund") > -1){
                resp = String.format(REFUND_ERROR_XML, e.getCode(), e.getMsg());
                logger.error(FORMAT_LOG, context.getMsgSeq(), resp);
                return resp;
            }
            resp = String.format(DEFAULT_ERROR_XML, e.getCode(), e.getMsg());
            logger.error(FORMAT_LOG, context.getMsgSeq(), resp);
            return resp;
        } catch (Exception e) {
            BizException bize = ApiBizException.UNKNOWN_EXCEPTION;
            logger.error(FORMAT_LOG, context.getMsgSeq(), String.format(DEFAULT_ERROR_XML, bize.getCode(), bize.getMsg()),e);
            return String.format(DEFAULT_ERROR_XML, bize.getCode(), bize.getMsg());
        }
    }

    private String getServiceCode(String reqXml) {
        if (StringUtils.isBlank(reqXml))
            return null;
        Matcher m = pattern.matcher(reqXml);
        if (m.find()) {
            return m.group(1);
        }
        return null;
    }

    private String getPartnerId(String reqXml) {
        if (StringUtils.isBlank(reqXml))
            return null;
        Matcher m = partnerIdPattern.matcher(reqXml);
        if (m.find()) {
            return m.group(1);
        }
        return null;
    }

    @Resource(name = "open-action-ActionMapper")
    private ActionMapper mapper;
    @Resource(name = "open-action-DispatcherHandlerChain")
    private HandlerChain handlerChain;

    private static final String SERVICECODE_MATCH_REGEX = "<serviceCode>([^<>]*)</serviceCode>";
    private Pattern pattern = Pattern.compile(SERVICECODE_MATCH_REGEX);
    private static final String PARTNERID_MATCH_REGEX = "<partnerId>([^<>]*)</partnerId>";
    private Pattern partnerIdPattern = Pattern.compile(PARTNERID_MATCH_REGEX);
    private static final String DEFAULT_ERROR_XML = "<Response><resultCode>%s</resultCode><resultDesc>%s</resultDesc></Response>";
    private static final String PAY_ERROR_XML = "<Response><resultCode>%s</resultCode><resultDesc>%s</resultDesc><payStatus>-1</payStatus></Response>";
    private static final String REVOKE_ERROR_XML = "<Response><resultCode>%s</resultCode><resultDesc>%s</resultDesc><revokeStatus>-1</revokeStatus></Response>";
    private static final String REFUND_ERROR_XML = "<Response><resultCode>%s</resultCode><resultDesc>%s</resultDesc><refundStatus>-1</refundStatus></Response>";

}

